// Segments in proc->gdt.
#define NSEGS     7

struct taskstate {
  uint link;         // Old ts selector
  uint esp0;         // Stack pointers and segment selectors
  ushort ss0;        //   after an increase in privilege level
  ushort padding1;
  uint *esp1;
  ushort ss1;
  ushort padding2;
  uint *esp2;
  ushort ss2;
  ushort padding3;
  void *cr3;
  uint *eip;
  uint eflags;
  uint eax;
  uint ecx;
  uint edx;
  uint ebx;
  uint *esp;
  uint *ebp;
  uint esi;
  uint edi;
  ushort es;
  ushort padding4;
  ushort cs;
  ushort padding5;
  ushort ss;
  ushort padding6;
  ushort ds;
  ushort padding7;
  ushort fs;
  ushort padding8;
  ushort gs;
  ushort padding9;
  ushort ldt;
  ushort padding10;
  ushort t;
  ushort iomb;
};

struct cpu {
  uchar id;                    // cpu id
  struct context *scheduler;   // 内核进程切换点
  struct taskstate ts;         // TSS描述符，主要用到其中段ss0:esp0即内核栈
  struct segdesc gdt[NSEGS];   // 描述符表
  volatile uint started;       // cpu启动标志
  int ncli;                    // pushcli的深度
  int oldif;                  // pushcli之前中断标志FL_IF
  
  struct cpu *cpu;
  struct proc *proc;           // 该cpu当前运行段进程
};

extern struct cpu cpus[NCPU];
extern int ncpu;

extern struct cpu *cpu asm("%gs:0");       // &cpus[cpunum()]
extern struct proc *proc asm("%gs:4");     // cpus[cpunum()].proc

struct context {
  uint edi;
  uint esi;
  uint ebx;
  uint ebp;
  uint eip;
};

enum procstate { UNUSED, EMBRYO, RUNNABLE, RUNNING };

struct proc {
  uint sz;                     // 进程内存大小
  uint pticks;
  pde_t* pgdir;                // 页目录表地址
  char *kstack;                // 进程内核栈栈底
  enum procstate state;        // 进程状态
  int pid;                     // 进程id
  struct proc *parent;         // 父进程
  struct trapframe *tf;        // 系统调用及初始化进程时候的进程调用栈
  struct context *context;     // 进程切换点
  char name[16];               // 进程名称
};

